package com.sk.util;

import com.sk.util.model.ITree;
import org.springframework.util.CollectionUtils;

import java.util.List;
import java.util.Map;
import java.util.function.Predicate;
import java.util.stream.Collectors;

/**
 * @author smy
 * {@code @date} 2023/1/18
 */
public class TreeUtil {

    public static <T extends ITree> List<T> buildTree(List<T> list, Predicate<T> topFilter) {
        //按照父类分组
        Map<Object, List<T>> group = LambdaUtil.listGroup(list, ITree::getParentId);
        //获取顶级树
        List<T> tree = list.stream().filter(topFilter).collect(Collectors.toList());
        //循环创建子树
        buildTreeCircle(tree, group);
        return tree;
    }

    private static <T extends ITree> void buildTreeCircle(List<T> tree, Map<Object, List<T>> group) {
        for (T t : tree) {
            List<T> children = group.get(t.getId());
            if (!CollectionUtils.isEmpty(children)) {
                t.getChildren().addAll(children);
                buildTreeCircle(children, group);
            }
        }
    }

    /**
     * 树过滤方法。
     * 组装完毕树以后，如果子元素符合条件，父节点也保留。
     *
     * @param tree       树结构
     * @param treeFilter 树过滤条件
     * @param <T>        泛型约束
     */
    public static <T extends ITree> boolean filterTree(List<T> tree, Predicate<T> treeFilter) {
        boolean listFlag = false;
        for (int i = tree.size() - 1; i >= 0; i--) {
            T t = tree.get(i);
            boolean oneFlag = filterTree(t.getChildren(), treeFilter) || treeFilter.test(t);
            if (oneFlag) {
                listFlag = true;
            } else {
                tree.remove(i);
            }
        }
        return listFlag;
    }
}
